#ifndef TABLAHASH_CPP
#define TABLAHASH_CPP

#include "TablaHash.h"

template <class C,class V>
TablaHash<C,V>::TablaHash(Puntero<Comparador<C>> comparadorClave, Puntero<FuncionHash<C>> funcionHash, nat largo)
{
	this->largo = this->PrimoMasCercano(largo);
	this->tabla = Array<Puntero<NodoTablaHashAbierto<C,V>>>(this->largo);
	for(int i=0; i<(int)tabla.Largo; i++)
	{
		tabla[i] = NULL;
	}
	this->funcionHash = funcionHash;
	this->comparadorClave = comparadorClave;
	this->cantElementos = 0;
}


template <class C,class V>
void TablaHash<C,V>::Insertar(const C x, const V y)
{
	int posAInsertar = this->funcionHash->CodigoDeHash(x) % this->largo;
	if(this->tabla[posAInsertar]==NULL)
	{
		this->tabla[posAInsertar] = new NodoTablaHashAbierto<C,V>();
		this->tabla[posAInsertar]->Clave = x;
		this->tabla[posAInsertar]->Valor = y;
		this->tabla[posAInsertar]->Sig = NULL;
	}else
	{
		Puntero<NodoTablaHashAbierto<C,V>> iter = this->tabla[posAInsertar];
		while(iter!=NULL && this->comparadorClave->SonDistintos(x,iter->Clave))
		{
			iter = iter->Sig;
			this->cantElementos++;
		}
		if(iter!=NULL)
		{
			iter->Valor = y;
		}else
		{
			Puntero<NodoTablaHashAbierto<C,V>> nodo = new NodoTablaHashAbierto<C,V>();
			nodo->Clave = x;
			nodo->Valor = y;
			nodo->Sig = this->tabla[posAInsertar];
			this->tabla[posAInsertar] = nodo;
			this->cantElementos++;
		}
	}
}

template <class C,class V>
V TablaHash<C,V>::Recuperar(const C x) const
{
	int pos = this->funcionHash->CodigoDeHash(x) % this->largo;

	Puntero<NodoTablaHashAbierto<C,V>> iter = this->tabla[pos];
	while(iter!=NULL && this->comparadorClave->SonDistintos(x,iter->Clave))
	{
		iter = iter->Sig;
	}
	return iter->Valor;
}

template <class C,class V>
bool TablaHash<C,V>::EstaDefinido(const C x) const
{
	int pos = this->funcionHash->CodigoDeHash(x) % this->largo;

	Puntero<NodoTablaHashAbierto<C,V>> iter = this->tabla[pos];
	while(iter!=NULL && this->comparadorClave->SonDistintos(x,iter->Clave))
	{
		iter = iter->Sig;
	}

	return iter!=NULL;
}

template<class C, class V>
void TablaHash<C,V>::ActualizarValor(const C& clave,const V& valorNuevo)
{
	nat pos = this->funcionHash->CodigoDeHash(clave) % this->largo;
	Puntero<NodoTablaHashAbierto<C,V>> nodoAux = this->tabla[pos];
	while (nodoAux!= NULL)
	{
		if(this->comparadorClave->SonDistintos(clave,nodoAux->Clave))
		{
			nodoAux->Valor = valorNuevo;
		}
		nodoAux = nodoAux->Sig;
	}
}


#endif
